package com.hk.service.product.impl;

import com.hk.app.utils.UniqueVersion;
import com.hk.commons.*;
import com.hk.commons.enm.ProdStatusEnum;
import com.hk.commons.entity.*;
import com.hk.commons.entity.product.AgreementToProduct;
import com.hk.commons.entity.product.Company;
import com.hk.commons.entity.product.ProductInfo;
import com.hk.commons.utils.sys.DataHelper;
import com.hk.commons.utils.sys.DateHelper;
import com.hk.commons.utils.sys.DateWeekOrHoliday;
import com.hk.commons.vo.*;
import com.hk.dao.base.impl.BaseServiceImpl;
import com.hk.service.kyc.*;
import com.hk.service.order.IParameter;
import com.hk.service.product.IAgreementToProduct;
import com.hk.service.product.ICompany;
import com.hk.service.product.IProductInfo;
import com.hk.service.sys.IAnswer;
import com.hk.service.sys.ISysUser;
import org.hibernate.StaleObjectStateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.hk.app.utils.SellRule.allowToBuy;

@Service
public class ProductInfoImpl extends BaseServiceImpl<ProductInfo> implements
		IProductInfo {

	private Logger logger = LoggerFactory.getLogger(ProductInfoImpl.class);

	@Value("${activity.baseUrl}")
	private String baseUrl;



	@Autowired
	private ICoupon couponService;

	@Autowired
	private IParameter parmService;


	@Autowired
	private IUserCard userCardService;

	@Autowired
	private ICard cardService;

	@Autowired
	private ISysUser userService;

	@Resource
	private JdbcTemplate jdbcTemplate;

	@Autowired
	private ILogUtil logService;

	private RestTemplate template = new RestTemplate();

	@Autowired
	private IAnswer answerService;

	@Autowired
	private ICompany companyService;

	@Autowired
	private IAgreementToProduct iagreementToProduct;

	@Autowired
	private IAgreement aggService;

	@Autowired
	private IAgreementToProduct iAgreementToProduct;

	@Override
	public ProductInfo findById(long id) {

		return getById(id);
	}

	@Override
	public Long add(ProductInfo u) {
		Long id = LongId.get();
		u.setId(id);
		return (Long) super.save(u);
	}

    @Override
    public void update(ProductInfo u) {
        logger.info("UPDATE_PRODUCT_SALE B4: prodId={} prostatus ={}, saleOut={} hotSale={} ",u.getId(), u.getProStatus(), u.getSaleOut(), u.getHotSale());

        if (u.getSaleOut() == null || u.getSaleOut() == 0) {
            // 如果已募集额度大于等于募集金额，则设置为满标,非热销
            if (u.getYraiseAccount().compareTo(u.getFinancingAccount()) == 1) {
                u.setHotSale(0);
                u.setSaleOut(1);
                //u.setSequence(Integer.MAX_VALUE);
            }

            // 如果已剩余额度小于最低起够金额，则设置为满标,非热销
            if (u.getSraiseAccount().compareTo(new BigDecimal(u.getSubscriptionOrigin())) == -1) {
                u.setHotSale(0);
                u.setSaleOut(1);
                //u.setSequence(Integer.MAX_VALUE);
            }
        }
        super.update(u);

        logger.info("UPDATE_PRODUCT_SALE 4B: prodId={} prostatus ={}, saleOut={} hotSale={} ",u.getId(), u.getProStatus(), u.getSaleOut(), u.getHotSale());

    }

	/**
	 * 设置预约金额
	 */
	@Override
	public boolean addBespeakAccount(Long id,
									 BigDecimal bespeakAmount) {
		// TODO Auto-generated method stub
		ProductInfo prod = findById(id);
		prod.setBespeakAccount(prod.getBespeakAccount().add(bespeakAmount));
		update(prod);
		return true;
	}

	/**
	 * 设置已付款金额
	 */
	@Override
	public boolean addYraiseAccount(Long id, BigDecimal account) {
		// TODO Auto-generated method stub
		ProductInfo prod = findById(id);

		// 募集额度
		BigDecimal financingAccount = prod.getFinancingAccount();

		// 剩余额度
		BigDecimal sraiseAccount = prod.getSraiseAccount().subtract(account);

		// 已打款金额
		BigDecimal yraiseAccount = prod.getYraiseAccount().add(account);

		// 如果打款额度小于等于募集额度， 并且剩余额度不小于 0， 则保存，否则返回false
		if (yraiseAccount.compareTo(financingAccount) != 1
				&& sraiseAccount.compareTo(new BigDecimal(0)) != -1) {
			prod.setYraiseAccount(yraiseAccount);
			prod.setSraiseAccount(sraiseAccount);
			update(prod);
			return true;
		} else {
			return false;
		}
	}

	@Override
	public ProductInfo getByInfo(Integer companyId, Integer proTerm,
								 BigDecimal maxYearRate) {
		ProductInfo prod = null;

		HqlFilter hqlFilter = new HqlFilter();
		hqlFilter.addEQFilter("issuerId", companyId);
		hqlFilter.addEQFilter("proTerm", proTerm);

		String maxYearRateStr = DataUtil.decimalToPercentage(maxYearRate);
		hqlFilter.addEQFilter("maxYearRate", maxYearRateStr);

		List<ProductInfo> prodList = new ArrayList<ProductInfo>();
		prodList = this.findByFilter(hqlFilter);
		if (prodList != null && prodList.size() > 0) {
			prod = prodList.get(0);
		}

		return prod;
	}

	@Override
    public synchronized boolean updAmountByPay(Long prodId,
                                  BigDecimal amount,
                                  Boolean payStatus) {

        try {
            logger.info("UPDATE_PRODUCT_AMOUNT Params:  prodId ={} payStatus={} amount={}", prodId, payStatus, amount);

            ProductInfo prod = findById(prodId);

            if (prod == null) {
                return false;
            }

            logger.info("UPDATE_PRODUCT_AMOUNT B4:  prodId={} amount={} YraiseAccount={} SraiseAccount={} version={}",
                    prodId, amount, prod.getYraiseAccount(), prod.getSraiseAccount(), prod.getVersion());

            if (payStatus) {
                // 增加已募集金额
                prod.setYraiseAccount(prod.getYraiseAccount().add(amount));
                // 减少剩余额度
                prod.setSraiseAccount(prod.getSraiseAccount().subtract(amount));

            } else {
                // 减少已募集金额
                prod.setYraiseAccount(prod.getYraiseAccount().subtract(amount));
                // 增加剩余额度
                prod.setSraiseAccount(prod.getSraiseAccount().add(amount));
            }

            update(prod);

            prod = findById(prodId);
            logger.info("UPDATE_PRODUCT_AMOUNT 4B:  prodId={} amount={} YraiseAccount={} SraiseAccount={} version={}",
                    prodId, amount, prod.getYraiseAccount(), prod.getSraiseAccount(), prod.getVersion());


        } catch (StaleObjectStateException exception) {
            exception.printStackTrace();
            logger.error("ROW WAS UPDATED WRONG VERSION = {}", exception);
            return false;
        } catch (Exception ex) {
            ex.printStackTrace();
            logger.error("updAmountByPay ERROR = {}", ex);
            return false;
        }

        return true;
    }

	@Override
	public BigDecimal getProDividend(ProductInfo prod, BigDecimal amount) {
		if (prod == null || amount == null) {
			return new BigDecimal("0.00");
		}
		BigDecimal yearRate = new BigDecimal(prod.getMaxYearRate().replace("%",
				"")).divide(new BigDecimal(100));
		int term = prod.getProTerm();
		BigDecimal dividend = amount.multiply(yearRate)
				.multiply(new BigDecimal(term))
				.divide(new BigDecimal(365), 5, BigDecimal.ROUND_HALF_UP);
		dividend = dividend.setScale(2, BigDecimal.ROUND_HALF_UP);
		return dividend;
	}

	@Override
	public BigDecimal getExtDividend(ProductInfo prod, Long userCardId,
									 BigDecimal amount) {
		UserCard userCard = userCardService.findById(userCardId);
		if (prod == null || userCard == null || prod.getProTerm() == null) {
			return new BigDecimal("0.00");
		}
		int term = prod.getProTerm();
		BigDecimal extraProfit = new BigDecimal(0);
		Card card = cardService.findById(userCard.getCardId());
		BigDecimal rate = card.getRate();
		extraProfit = amount.multiply(rate).multiply(new BigDecimal(term))
				.divide(new BigDecimal(365), 5, BigDecimal.ROUND_HALF_UP);
		// 使用加息券后单笔额外增加的利润最高为5000元，超过5000元仍按5000元发放；
		if (extraProfit.compareTo(new BigDecimal(5000)) == 1) {// 1是大于
			extraProfit = new BigDecimal("5000.00");
		}
		extraProfit = extraProfit.setScale(2, BigDecimal.ROUND_HALF_UP);
		return extraProfit;
	}

	@Override
	public Map<String, Long> getOrderDate(ProductInfo prod) {
		Map<String, Long> map = new HashMap<>();
		Long startTimeLong = null;
		if (prod != null && prod.getDivStartType() != null) {
			Integer divStartType = prod.getDivStartType();
			System.out.println("divStartType:" + divStartType);
			Calendar carCalendar = Calendar.getInstance();
			if (divStartType == ConstantProduct.PRO_DIV_START_TYPE_DADD1) {
				startTimeLong = DateWeekOrHoliday.getNextDD(carCalendar, 1);

			} else if (divStartType == ConstantProduct.PRO_DIV_START_TYPE_DADD2) {
				startTimeLong = DateWeekOrHoliday.getNextDD(carCalendar, 2);

			} else if (divStartType == ConstantProduct.PRO_DIV_START_TYPE_TADD1) {
				startTimeLong = DateWeekOrHoliday.getNextTD(carCalendar, 1);

			} else if (divStartType == ConstantProduct.PRO_DIV_START_TYPE_TADD2) {
				startTimeLong = DateWeekOrHoliday.getNextTD(carCalendar, 2);

			}
		}
		Long endTimeLong = null;
		if (prod != null && prod.getProTerm() != null) {
			endTimeLong = DateWeekOrHoliday.getNextD(startTimeLong,
					prod.getProTerm());
		}
		map.put("endTimeLong", endTimeLong);
		map.put("startTimeLong", startTimeLong);
		return map;

	}

	@Override
	public Integer validateRaiseMoney(ProductInfo productInfo, BigDecimal amount) {
		BigDecimal leftAmount = productInfo.getSraiseAccount();
		if (leftAmount.compareTo(amount) == 0) {// 返回的结果是int类型,-1表示小于,0是等于,1是大于
			return 0;
		}

		return 1;
	}

	@Override
	public CheckInfo checkLimit(Long userId, Long productId, BigDecimal buyAmount) {
		CheckInfo checkInfo = new CheckInfo();
		checkInfo.setResult(false);
		ProductInfo prod = this.findById(productId);
		//01: 产品不存在
		if (prod == null) {
			checkInfo.setResultMsg("产品不存在！");
			return checkInfo;
		}

		//02： 产品部允许购买
		if (prod.getProStatus() != ConstantProduct.PRODUCT_RELEASE_STATE_TRUE) {
			checkInfo.setResultMsg("该产品目前不能进行购买，此次购买失败！");
			return checkInfo;
		}

		//03： 产品满标
		if (prod.getSaleOut() != null && prod.getSaleOut() == ConstantProduct.PRO_SALE_OUT) {
			checkInfo.setResultMsg("该产品已满标不能进行购买，此次购买失败！");
			return checkInfo;
		}

		//04: 用户未注册
		if (userId == null || userService.findById(userId) == null) {
			checkInfo.setResultMsg("用户不存在或用户未注册，暂不能购买！");
			return checkInfo;
		}

		//05: 体验标只支持体验金进行购买
		if(prod.getSaleType() == ConstantProduct.PRODUCT_TEST_PRODUCT ){
			if(buyAmount.compareTo(BigDecimal.valueOf(0)) == 1){
				checkInfo.setResultMsg("体验标只能用体验金进行购买，不能额外输入金额！");
				return checkInfo;
			}
		}else{

            //06: 非体验标产品购买额度小于最低起够金额
            BigDecimal minBuyAmount = new BigDecimal(prod.getSubscriptionOrigin());
            if (buyAmount == null || buyAmount.compareTo(minBuyAmount) == -1) {
                checkInfo.setResultMsg("该产品的最低起够金额为" + minBuyAmount + ", 请输入正确的金额！");
                return checkInfo;
            }

            //追加金额必须是整倍数
            BigDecimal minAppendAmount = prod.getMinAppendAccount();
            if (!allowToBuy(buyAmount, minBuyAmount, minAppendAmount)) {
                checkInfo.setResultMsg("该产品的追加金额必须为" + minAppendAmount + "的倍数, 请输入正确的金额！");
                return checkInfo;
            }

        }

		//07: 限购产品购买笔数大于限购笔数
		Integer alreadyBuyNum = getBuyNum(userId, prod.getParId());
		if (prod.getLimitNum() != null && alreadyBuyNum >= prod.getLimitNum()) {
			checkInfo.setResultMsg("亲，您已购买过该产品，不能重复购买！");
			return checkInfo;
		}

		//08: 限购产品购买金额大于限购笔数
		if(prod.getLimitAmount() != null && buyAmount.compareTo(prod.getLimitAmount()) == 1){
			checkInfo.setResultMsg("亲，本产品限购" + prod.getLimitAmount() + "元哦！");
			return checkInfo;
		}

		//09:产品余额不足
		BigDecimal leftAmount   = prod.getSraiseAccount();
		if (-1 == leftAmount.compareTo(buyAmount)) {// 返回的结果是int类型,-1表示小于,0是等于,1是大于
			// 剩余额度小于购买额度，则超募
			checkInfo.setResultMsg("该产品剩余额度为：" + leftAmount + "元, 额度不足，此次购买失败！");
			return checkInfo;
		}

		checkInfo.setResult(true);
		return checkInfo;
	}

	@Override
	public CheckInfo checkBeforeCreateOrder(Long userId, Long productId,BigDecimal byAmount,  Long userCardId, String nowVersion) {
		CheckInfo checkInfo = new CheckInfo();
		checkInfo.setResult(false);



		checkInfo = this.checkProdBuyVersion(nowVersion, "2.6.1", productId, userId);
		if(checkInfo.getResult() == false){
			logger.info("checkBeforeCreateOrder, user app version is not latest , can not by prod");
			return  checkInfo;
		}
		logger.info("check user app version pass");


		checkInfo = this.checkProdBuyKyc(productId, userId);
		if(checkInfo.getResult() == false){
			logger.info("checkBeforeCreateOrder, user kyc not finished , can not by prod");
			return  checkInfo;
		}
		logger.info("check user kyc pass");

		Boolean limitCheckResult = checkLimit(userId, productId, byAmount).getResult();
		if(!limitCheckResult ){
			return  checkLimit(userId, productId, byAmount);
		}

		ProductInfo prod = this.findById(productId);

		//****** 开始进行卡券校验 开始进行非卡券校验，必须进行

		//如果产品是体验标，并且没有使用卡券，则购买失败
		if(prod.getSaleType() == ConstantProduct.PRODUCT_TEST_PRODUCT ) {
			checkInfo.setResultMsg("该体验标仅支持通过体验金进行购买，此次购买失败！");
			checkInfo.setResult(false);
			return checkInfo;
		}

		//如果产品是加息产品，判断用户是否有购买权限
		logger.info("prod sale type = {}", prod.getSaleType() );
		if(prod.getSaleType()==ConstantProduct.PRODUCT_SALETYPE_04){
			logger.info("购买加息产品，开始检查");

			CheckInfo check = canBuy(userId);
			logger.info("购买加息产品，检查结果是={}", check.toString());

			if(check.getResult() == false) {
				logger.info("购买加息产品，检查结果是={}", check.toString());
				return check;
			}
		}


		//待售产品不允许购买
		if (prod.getWaitSale() == null || prod.getWaitSale() == ConstantProduct.PRODUCT_WAITSALE_TRUE) {
			checkInfo.setResultMsg("该产品未开售，此次购买失败！");
			checkInfo.setResult(false);
			return checkInfo;
		}

		//如果没有使用卡券，直接返回
		if(userCardId == null){
			checkInfo.setResult(true);
			return checkInfo;
		}

		//****** 开始进行卡券校验
		checkInfo.setResult(false);

		UserCardMsg userCardMsg = couponService.getCouponInfo(userId, userCardId);
		List<ProductUsableCardMsg> productUsableCardMsgs = couponService.getProductUsableCardMsgList(productId);

		//如果卡券不存在，则购买失败
		if (userCardId != null && userCardMsg == null) {
			checkInfo.setResultMsg("用户使用的卡券不存在，此次购买失败！");
			checkInfo.setResult(false);
			return checkInfo;
		}

		//如果该产品没有适用本卡券，则购买失败
		if(!productUsableCardMsgs.stream().anyMatch(p ->p.getCardid().equals(userCardMsg.getCardId()))){
			checkInfo.setResultMsg("对不起，您选择的优惠券不适用该产品，此次购买失败！");
			return checkInfo;
		}

		//加息券验证加息天数是否大于产品期限
		if(userCardMsg.getCardType() == ConstantCard.CARD_TYPE_JXQ && userCardMsg.getCardDays() > prod.getProTerm() ){
			checkInfo.setResultMsg("对不起，您选择的优惠券不适用该产品，此次购买失败！");
			return checkInfo;
		}

		//购买金额是否大于贴息券的起购金额
		if(userCardMsg.getCardType() == ConstantCard.CARD_TYPE_DJQ && productUsableCardMsgs.stream().
				filter(p ->p.getCardid().equals(userCardMsg.getCardId()))
				.anyMatch(p->p.getConditionNum()>byAmount.longValue())){
			checkInfo.setResultMsg("对不起，您输入的投资金额小于贴息券的起购金额，此次购买失败！");
			return checkInfo;
		}

		//如果产品不能使用加息券，并且所选择的是加息券，则购买失败
		if(prod.getUseCard()==ConstantProduct.PRODUCT_USE_JXQ_FALSE &&
				userCardMsg.getCardType()==ConstantCard.CARD_TYPE_JXQ) {
			checkInfo.setResultMsg("该产品不能使用用加息券进行购买，此次购买失败！");
			checkInfo.setResult(false);
			return checkInfo;
		}


		//如果卡不是未激活状态，则购买失败
		if (userCardMsg.getStatus() != ConstantCard.CARD_STATUS_NO_ACTIVE) {
			checkInfo.setResultMsg("用户使用的卡券已使用或已过期，此次购买失败！");
			checkInfo.setResult(false);
			return checkInfo;
		}

		//如果产品不是体验标，但选择的是体验金，则购买失败
		if (prod.getSaleType() != ConstantProduct.PRODUCT_TEST_PRODUCT && userCardMsg.getCardType() == ConstantCard.CARD_TYPE_TYJ){
			checkInfo.setResultMsg("非体验标不能用体验金进行购买，此次购买失败！");
			checkInfo.setResult(false);
			return checkInfo;
		}

		//如果产品是体验标，并且选择的不是体验金，则购买失败
		if(prod.getSaleType()==ConstantProduct.PRODUCT_TEST_PRODUCT && userCardMsg.getCardType()!=ConstantCard.CARD_TYPE_TYJ){
			checkInfo.setResultMsg("该产品为体验标，请选择体验金进行购买，此次购买失败！");
			checkInfo.setResult(false);
			return checkInfo;
		}

		checkInfo.setResult(true);
		return checkInfo;
	}


	@Override
	public BigDecimal getExtDividend(ProductInfo prod, BigDecimal rate,
			BigDecimal amount) {
		
		BigDecimal extraProfit = new BigDecimal(0.00);
		int term = prod.getProTerm();
		
		extraProfit = amount.multiply(rate).multiply(new BigDecimal(term))
				.divide(new BigDecimal(365), 5, BigDecimal.ROUND_HALF_UP);
		// 使用加息券后单笔额外增加的利润最高为5000元，超过5000元仍按5000元发放；
		if (extraProfit.compareTo(new BigDecimal(5000)) == 1) {// 1是大于
			extraProfit = new BigDecimal("5000.00");
		}
		extraProfit = extraProfit.setScale(2, BigDecimal.ROUND_HALF_UP);
		
		return extraProfit;
	}


	public Integer getBuyNum(Long userId,  Long parId  ){
		Integer size = 0;
		String sql = " select count(1) from t_order_info  o left join t_product_info p on o.productId = p.id where  o.userId = "+ userId + " and o.payStatus in (2,3,4) "
				+ " and p.parId = " + parId;
		logger.info("getBuyNum sql = {}", sql);
		size = jdbcTemplate.queryForObject(sql, Integer.class);

		return size == null ? Integer.valueOf(0) : size;
	}

	@Override
	public List<ProductInfo> page(int pageNo, int pageSize, List<ProductInfo> list){
		logger.info("get product list pageNo={}, pageSize={}", pageNo, pageSize);

		pageNo = pageNo - 1;

		if(pageNo < 0){
			pageNo = 0;
		}

		List<ProductInfo> result = new ArrayList<ProductInfo>();
		if(list != null && list.size() > 0){
			int allCount = list.size();

			int pageCount = (allCount + pageSize-1) / pageSize; //总页数

			if(pageNo >= pageCount){
				pageNo = pageCount;
			}
			int start = pageNo * pageSize;

			int end = start +  pageSize;

			if(end >= allCount){
				end = allCount;
			}
			for(int i = start; i < end; i ++){
				result.add(list.get(i));
			}
		}
		logger.info("get product result size ={}", result.size());
		return (result != null && result.size() > 0) ? result : null;
	}

	@Override
	public void moveSequence(int sequence) {
		logger.info("will update all the sequence to unll where sequence={}", sequence);
		HqlFilter hqlFilter = new HqlFilter( );
		hqlFilter.addEQFilter("sequence", sequence);
		List<ProductInfo> productInfoList = findByFilter(hqlFilter);
		if(productInfoList != null  && productInfoList.size() > 0){
			logger.info("productInfoList  size={}", productInfoList.size());
		}

		if(productInfoList == null || productInfoList.size() == 0){
			return;
		}else {
			for (ProductInfo prod : productInfoList) {
				logger.info("will update sequence to null proName={}", prod.getName());
				prod.setSequence(null);
				update(prod);
			}
		}
	}

	@Override
	public String getTotalRateStr(Long productId){

		ProductInfo prod = findById(productId);

		String yearRateStr = prod.getMaxYearRate();

		BigDecimal addRate = getAddRate(productId);

		String addRateStr = null;

		if(addRate != null && addRate.compareTo(new BigDecimal(0.00)) == 1){
			addRateStr = DataHelper.chgBigDecimalToPrecent(addRate, 2);
		}

		if(addRateStr != null){
			yearRateStr = yearRateStr + "+" + addRateStr;
		}

		return yearRateStr;
	}

	@Override
	public BigDecimal getTotalRate(Long productId) {
		logger.info("getTotalRate   productID={}", productId);

		ProductInfo prod = findById(productId);

		String yearRateStr = prod.getMaxYearRate();

		BigDecimal addRate = getAddRate(productId);

		BigDecimal yearRate = DataHelper.chgPrecentToBigDecimal(yearRateStr);

		return yearRate.add(addRate);
	}




	@Override
	public BigDecimal getAddRate(Long productId) {

		BigDecimal result = new BigDecimal(0.00);
		logger.info("getAddRate   productID={}", productId);
		ProductInfo prod = findById(productId);

		if(checkUnNormalDay() == false){
			logger.info("productID={}, 是普通时间进行购买", productId);
			return result;
		}

		logger.info("productID={}, 是特殊时间进行购买", productId);

		Parameter parm  = parmService.getByName(ConstantParm.WY_DATES_1);
		if(parm == null){
			logger.error("<------------------ERROE, WY_DATES_1 没有设置---------------------->");
			return result;
		}

		String data01 = parm.getValue01();
		String data03 = parm.getValue03();

		String extRateStr = null;
		String newData = DateHelper.getNowDateByFormat("yyyyMMdd");

		Parameter parmProd  = parmService.getByName(ConstantParm.WY_PROD);

		if( prod.getProdFlag01() == null || (prod.getProdFlag01().equals(parmProd.getValue01()) == false
				&& prod.getProdFlag01().equals(parmProd.getValue02()) == false)){
			logger.info("productID={}, 不是活动产品", productId);
			return result;
		}

		logger.info("productID={}, 是活动产品", productId);

		if (newData.equals(data01)) {
			logger.info("time 和 WY_DATES_1 中第1个时间相同");
			extRateStr = parm.getValue02();
		} else if (newData.equals(data03)) {
			logger.info("time 和 WY_DATES_1 中第2个时间相同");
			extRateStr = parm.getValue04();
		} else {
			logger.info("time 和 WY_DATES_1 中第1个时间， 第2个时间都不相同");
			//加息产品
			if (prod.getSaleType() == ConstantProduct.PRODUCT_SALETYPE_04) {
				extRateStr = prod.getAddRate();
			}
		}

		logger.info("extRateStr = {}", extRateStr);

		if(extRateStr != null){
			result = DataHelper.chgPrecentToBigDecimal(extRateStr);
		}

		logger.info("addRate before return  = {}", result);

		return result;
	}



	@Override
	public Boolean checkUnNormalDay( ){

		Boolean checkResult = false;

		Parameter parm02  = parmService.getByName(ConstantParm.WY_DATES_2);

		if(parm02 == null){
			logger.error("<---------------------ERROR, WY_DATES_2 没有设置————————————>");
			return null;
		}

		Long nowTime = System.currentTimeMillis();


		DateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");

		try {
			Long startTime = dateFormat.parse(parm02.getValue01()).getTime();

			Long endTime = dateFormat.parse(parm02.getValue02()).getTime();

			if(nowTime.longValue() > startTime.longValue() && nowTime.longValue() < endTime.longValue()){
				//logger.info("time 在 WY_DATES_2 中第1个时间， 第2个时间内 ");

				return true;
			}else{
				//logger.info("time 不在 WY_DATES_2 中第1个时间， 第2个时间内");
				return false;
			}
		} catch (ParseException e) {
			e.printStackTrace();
		}


		return checkResult;
	}

	@Override
	public CheckInfo canBuy(Long userId) {
		CheckInfo checkInfo = new CheckInfo();
		checkInfo.setResult(false);
		checkInfo.setResultMsg("购买失败！");

		//检查活动是否开始
		if(checkUnNormalDay() == false){
			logger.info("非活动期间，不能购买该高息标产品！");
			checkInfo.setResultMsg("非活动期间，不能购买该高息标产品！");
			return checkInfo;
		}


		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddkkmmss", Locale.CHINA);
		Parameter wyDates1 = parmService.getByName("WY_DATES_1");

		if(wyDates1 == null ){
			//logger.info("wyDates1 is null");
			return checkInfo;
		}

		//logger.info("wyDates1 = {}", wyDates1.toString());


		LocalDateTime firstDateTime = LocalDateTime.parse(String.format("%s000000", wyDates1.getValue01()), dateTimeFormatter);
		LocalDateTime afterFirstDateTime = firstDateTime.plusDays(1L);

		LocalDateTime secondDateTime = LocalDateTime.parse(String.format("%s000000", wyDates1.getValue03()), dateTimeFormatter);
		LocalDateTime afterSecondDateTime = secondDateTime.plusDays(1L);

		Parameter wyDates2 = parmService.getByName("WY_DATES_2");


		if(wyDates2 == null ){
			//logger.info("wyDates2 is null");
			return checkInfo;
		}

		//logger.info("wyDates2 = {}", wyDates2.toString());


		LocalDateTime wyBegin = LocalDateTime.parse(wyDates2.getValue01(), dateTimeFormatter);
		LocalDateTime wyEnd = LocalDateTime.parse(wyDates2.getValue02(), dateTimeFormatter);


		//区别活动类型产品
		Parameter wyProd = parmService.getByName(ConstantParm.WY_PROD);

		//设置限定金额
		Parameter parm04 = parmService.getByName(ConstantParm.WY_CUM_INV_AMOUNT);

		BigDecimal amount = new BigDecimal(parm04.getValue01());

		logger.info("用户需要购买的最低额度amount ={}", amount);


		String data01 = wyDates1.getValue01();
		String data03 = wyDates1.getValue03();

		String newData = DateHelper.getNowDateByFormat("yyyyMMdd");

		if(newData.equals(data01) || newData.equals(data03)){
			logger.info("在特殊的两天里，不允许购买！");
			checkInfo.setResultMsg("非活动期间，不能购买该高息标产品！");
			return checkInfo;
		}


		// 活动内， 排除了那两天特殊的日子
		String sql = String.format("select sum(successAmount) as successAmount from t_order_info where userId = ? and (orderCreatedOn >= ? and orderCreatedOn < ?) and (orderCreatedOn < ? or orderCreatedOn > ?) and (orderCreatedOn < ? or orderCreatedOn > ?) and productId in ( select id from t_product_info where saleType = 1 and prodFlag01 = '%s' )", wyProd.getValue01());

		BigDecimal  successAmount = this.jdbcTemplate.queryForObject(sql, new Object[] {
				userId,
				Timestamp.valueOf(wyBegin).getTime(),
				Timestamp.valueOf(wyEnd).getTime(),

				Timestamp.valueOf(firstDateTime).getTime(),
				Timestamp.valueOf(afterFirstDateTime).getTime(),

				Timestamp.valueOf(secondDateTime).getTime(),
				Timestamp.valueOf(afterSecondDateTime).getTime()

		}, BigDecimal.class);

		logger.info("用户 successAmount ={}", successAmount);

		if (successAmount == null || successAmount.compareTo(amount) == -1) {
			logger.info("对不起，该产品需购买岁半通财（180天）或岁岁盈年（365天）累计满" + amount +"元方可购买");
			checkInfo.setResultMsg("对不起，该产品需购买岁半通财（180天）或岁岁盈年（365天）累计满" + amount +"元方可购买");
			checkInfo.setResult(false);
			return checkInfo;
		}else{
			checkInfo.setResult(true);
			checkInfo.setResultMsg("购买额度达到"+ amount + "，允许购买！");
		}

		logger.info("check can buy result = {}", checkInfo);

		return checkInfo;
	}

	public static void main(String[] args) throws Exception {
		String text = "20170318000000";
		String text1 = "20170317";

		DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyyMMddkkmmss");
		DateTimeFormatter dateFormater = DateTimeFormatter.ofPattern("yyyyMMdd");

		LocalDateTime dateTime = LocalDateTime.parse(text, dateTimeFormatter);
		LocalDateTime date2 = LocalDateTime.parse(String.format("%s000000", text1), dateTimeFormatter);

		System.out.println(dateTime);
		System.out.println(date2);
	}

	@Override
	public void  addLogRecord(Long productId, Long userId){
		logger.info("will add log record");
		try{
			ProductInfo productInfo = findById(productId);

			LogUtil logRecord = new LogUtil();

			logRecord.setActUserId(userId);
			logRecord.setType(ConstantLog.LOG_TYPE_PRODUCT_PAYBACK);
			logRecord.setChgDesc("产品回款划拨，产品名称：" + productInfo.getName());

			logRecord.setRecordId(productInfo.getId());
			logRecord.setUserId(userId);

			ProdPayBackLogInfo info = new ProdPayBackLogInfo();
			info.setProductId(productId);
			info.setName(productInfo.getName());


			// 在日志表中保存修改之前的镜像
			String beforeImgStr = JsonUtils.toJson(info);

			logRecord.setBeforeImg(beforeImgStr);

			info.setPayBackStatus(1);
			logger.info("产品回款划拨，更改产品的回款状态  productId = {}, userId={}",productId, userId);

			// 在日志中保存修改之后的镜像
			String afterImgStr = JsonUtils.toJson( info);
			logRecord.setAfterImg(afterImgStr);

			// 加入日志表中
			logService.add(logRecord);

		}catch (Exception e){
			logger.error("产品回款划拨，添加日志错误 e={}", e);
		}

	}


	@Override
	public OrderActCheckMsg checkAct(Long userId, Long productId, BigDecimal byAmount) {

		OrderActCheckMsg orderActCheckMsg;

			try{

				String url = baseUrl + "api/activity/getOrderBeforePopMsg" + "?userId=" + userId + "&productId="+ productId + "&orderAmount=" + byAmount;

				logger.info("checkAct getCouponInfo url = {}", url);

				if (template.getForObject(url, String.class) != null) {

					String respStr  =  template.getForObject(url, String.class);

					logger.info("respStr = {}", respStr);

					JsonResult<OrderActCheckMsg> respResult =  JsonUtils.toBean(respStr, JsonResult.class, OrderActCheckMsg.class);

					orderActCheckMsg = respResult.result;

				}else{
					orderActCheckMsg =new OrderActCheckMsg ();


				}
			}catch(Exception e){
				orderActCheckMsg = new OrderActCheckMsg ();
				logger.error(" getActCheckMsg error msg ={}",e.getMessage());
			}


		return orderActCheckMsg;
	}
	@Override
	public CheckInfo checkProdBuyKyc(Long productId, Long userId) {
		logger.info("checkProdBuyKyc will start productId={}, userId={}", productId, userId);
		CheckInfo checkInfo = new CheckInfo();

		ProductInfo prod = this.findById(productId);

		//检查产品是否需要做风险测评
		if( this.needCheckKyc(prod) == false){
			logger.info("not need to do the kyc");
			checkInfo.setResult(true);
			return  checkInfo;
		}

		logger.info("product need to do the kyc");

		if(answerService.checkByUserId(userId) == false){
			logger.info("为了您的资金安全，请到首页-投资测评完成测评后再进行购买");
			checkInfo.setResult(false);
			checkInfo.setResultMsg("为了您的资金安全，请到首页-投资测评完成测评后再进行购买");
		}else if(answerService.moreThanOneYear(userId) == true){
			logger.info("您的风险测评已过期，请重新测评后再进行购买");
			checkInfo.setResult(false);
			checkInfo.setResultMsg("您的风险测评已过期，请重新测评后再进行购买");
		}else{
			logger.info("user has finish the kyc.");
			checkInfo.setResult(true);
		}
		return  checkInfo;
	}

	@Override
	public List<Long> getAgreementIds(Long productId) {
		return iagreementToProduct.getAgreementIdsByProductId(productId);
	}

	@Override
	public ProductInfoRes getProductInfoResById(Long productId) {
		if(productId == null)
			return null;

		ProductInfo productInfo = this.findById(productId);
		if (productInfo == null)
			return null;

		ProductInfoRes singleResp = new ProductInfoRes();

		ReqToModelHelper.copyReqValueToModel(productInfo, singleResp);

		try {
			String introduceTxt, incomeTxt, riskctrlTxt, signFlowTxt = "";
			if (productInfo.getIntroduce() != null) {

				introduceTxt = new String(productInfo.getIntroduce(), "UTF-8");

				singleResp.setIntroduceTxt(introduceTxt);
			}
			if (productInfo.getIncome() != null) {
				incomeTxt = new String(productInfo.getIncome(), "UTF-8");
				singleResp.setIncomeTxt(incomeTxt);
			}
			if (productInfo.getRiskctrl() != null) {
				riskctrlTxt = new String(productInfo.getRiskctrl(), "UTF-8");
				singleResp.setRiskctrlTxt(riskctrlTxt);
			}

			if (productInfo.getSignFlow() != null) {
				signFlowTxt = new String(productInfo.getSignFlow(), "UTF-8");
				singleResp.setSignflowTxt(signFlowTxt);
			}

			singleResp.setBuyType(productInfo.getBuyType());

			if (productInfo.getProdTopType().equals(Constant.PRODUCT_TYPE_2)) {
				if(productInfo.getMinYearRate().equals(productInfo.getMaxYearRate())){
					singleResp.setYearRate(productInfo.getMaxYearRate());
					singleResp.setTotalRate(DataHelper.chgPrecentToBigDecimal(productInfo.getMaxYearRate()));
					singleResp.setTopSaleStr(productInfo.getMaxYearRate());
				}else{
					singleResp.setYearRate(productInfo.getMinYearRate() + " ~ " + productInfo.getMaxYearRate());

					singleResp.setTotalRate(this.getTotalRate(productId));

					singleResp.setTopSaleStr(productInfo.getMinYearRate() + " ~ " + productInfo.getMaxYearRate());
				}

			} else if (productInfo.getProdTopType().equals(
					Constant.PRODUCT_TYPE_3)) {
				singleResp.setYearRate("浮动收益");
				singleResp.setTopSaleStr("浮动收益");
			} else if (productInfo.getProdTopType().equals(
					Constant.PRODUCT_TYPE_4)) {
				singleResp.setYearRate("不低于" + productInfo.getMinYearRate());
				singleResp.setTopSaleStr("不低于" + productInfo.getMinYearRate());
			}

			//如果是额外收益类产品
			if(productInfo.getSaleType() == ConstantProduct.PRODUCT_SALETYPE_04){
				singleResp.setYearRate(productInfo.getMaxYearRate()  + "+" +  productInfo.getAddRate());
				singleResp.setTotalRate(this.getTotalRate(productId));
				singleResp.setTotalRateStr(this.getTotalRateStr(productId));
			}



			// 添加风险等级
			if (StringHelper.isNotEmpty(productInfo.getRiskLevel())) {
				singleResp.setRiskLevel(productInfo.getRiskLevel());
			}

			if(StringHelper.isNotEmpty(productInfo.getLabel01())){
				singleResp.setLabel01(productInfo.getLabel01());
			}

			if(StringHelper.isNotEmpty(productInfo.getLabel02())){
				singleResp.setLabel02(productInfo.getLabel02());
			}

			if(productInfo.getParId() != null){
				singleResp.setParId(productInfo.getParId());
			}


			if(StringHelper.isNotEmpty(productInfo.getLabel03())){
				singleResp.setLabel03(productInfo.getLabel03());
			}

			if(productInfo.getLimitNum() != null){
				singleResp.setLimitNum(productInfo.getLimitNum());
			}

			if(productInfo.getLimitAmount() != null){
				singleResp.setLimitAmount(productInfo.getLimitAmount());
			}

			// 是否可用加息券
			if (productInfo.getUseCard() != null) {
				singleResp.setUseCard(productInfo.getUseCard());
			}

			// 已募集金额
			if (productInfo.getYraiseAccount() != null) {
				BigDecimal maxYarseAccount = productInfo.getFinancingAccount();

				if (productInfo.getYraiseAccount().compareTo(maxYarseAccount) == 1) {
					singleResp.setYraiseAccount(maxYarseAccount);
				} else {
					singleResp.setYraiseAccount(productInfo.getYraiseAccount());
				}

			}

			// 剩余额度
			if (productInfo.getSraiseAccount() != null) {

				BigDecimal minSraiseAccount = new BigDecimal("0");
				if (productInfo.getSraiseAccount().compareTo(minSraiseAccount) == -1) {
					singleResp.setSraiseAccount(minSraiseAccount);
				} else {
					singleResp.setSraiseAccount(productInfo.getSraiseAccount());
				}
			}

			// 产品销售状态属性
			if (productInfo.getHotSale() != null) {
				singleResp.setHotSaleStr(ProdStatusEnum.getStatus(productInfo
						.getHotSale()));
			}

			// 添加产品发行公司的信息
			Company co = companyService.findById(productInfo.getIssuerId());
			singleResp.setIssuerStr(co.getName());

			// 添加产品合同属性
			if (productInfo.getContractId() != null) {
				Agreement agreement = aggService.findById(productInfo
						.getContractId());
				if (agreement != null) {
					singleResp.setContractTitle(agreement.getName());
					singleResp.setContractId(agreement.getId());
				}
			}


			//添加合同属性列表(多个合同)
			List<AgreementToProduct> agreementList = iAgreementToProduct.findByProductId(productInfo.getId());
			List<Map<String,Object>> agreements = null;
			if(agreementList == null || agreementList.size()==0){
				Map<String,Object> argeementMap = new HashMap<>();
				argeementMap.put("contractId",singleResp.getContractId());
				argeementMap.put("contractTitle",singleResp.getContractTitle());
				argeementMap.put("contractUrl","");
				agreements = new ArrayList<>();
				agreements.add(argeementMap);
				singleResp.setAgreements(agreements);
			}else{
				Map<String,Object> argeementMap;
				agreements = new ArrayList<>();
				for(AgreementToProduct agreement:agreementList){
					argeementMap = new HashMap<>();
					argeementMap.put("contractId",agreement.getAgreementId());
					argeementMap.put("contractTitle",agreement.getAgreementTitle());
					argeementMap.put("contractUrl","");
					agreements.add(argeementMap);
				}
				singleResp.setAgreements(agreements);
			}



			// 添加产品父标
			if (productInfo.getParId() != null) {
				ProductInfo proParInfo = this.findById(productInfo
						.getParId());
				if(proParInfo != null) {
					singleResp.setParName(proParInfo.getName());
				}
			}

			// 如果满标，则更改已募集额度和剩余额度
			if (productInfo.getSaleOut() != null && productInfo.getSaleOut() == ConstantProduct.PRO_SALE_OUT) {
				BigDecimal minSraiseAccount = new BigDecimal("0");
				// 剩余额度为0
				singleResp.setSraiseAccount(minSraiseAccount);
				// 已募集额度为总募集
				//singleResp.setYraiseAccount(productInfo.getFinancingAccount());
				singleResp.setYraiseAccount(productInfo.getYraiseAccount());
			}

			if(productInfo.getActBack() != null){
				singleResp.setActBack(productInfo.getActBack());
			}

			if(StringHelper.isNotEmpty(productInfo.getActFlag())){
				singleResp.setActFlag(productInfo.getActFlag());
			}

		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return singleResp;
	}

	@Override
	public CheckInfo checkProdBuyVersion(String nowVersion, String limitVersion, Long productId, Long userId) {
		logger.info("checkProdBuyVersion will start nowVersion={}, limitVersion={}", nowVersion, limitVersion);
		CheckInfo checkInfo = new CheckInfo();
		ProductInfo prod = this.findById(productId);

		Company com = companyService.findById(prod.getIssuerId());

		//检查贵州金交所的产品
		if(com != null && com.getName().equals("贵州场外") == false){
			checkInfo.setResult(true);
			return  checkInfo;
		}

		if(StringHelper.isEmpty(nowVersion) ){
			logger.info("您的华财通版本过低，请升级到最新版本后再进行购买, userId={}", userId);
			checkInfo.setResult(false);
			checkInfo.setResultMsg("您的华财通版本过低，请升级到最新版本后再进行购买");
			return checkInfo;
		}

		Boolean versionCheckResult = null;
		try {
			versionCheckResult = new UniqueVersion(nowVersion).isEqualGreaterThan(new UniqueVersion("2.6.1"));
		} catch (Exception e) {
			e.printStackTrace();
			versionCheckResult = false;
			logger.error("checkProdBuyVersion error e={}", e);
		}

		if(versionCheckResult == false){
			logger.info("您的华财通版本过低，请升级到最新版本后再进行购买, userId={}", userId);
			checkInfo.setResult(false);
			checkInfo.setResultMsg("您的华财通版本过低，请升级到最新版本后再进行购买");
			return checkInfo;
		}

		checkInfo.setResult(true);
		return checkInfo;

	}


	public boolean needCheckKyc(ProductInfo prod) {
		Parameter parm = parmService.getByName(ConstantParm.CHECK_KYC);

		if (parm == null) {
			return false;
		}

		if (StringHelper.isNotEmpty(parm.getValue01()) && parm.getValue01().equals("ALL")) {
			return true;
		} else if (parm.getValue01().equals("NOT_ALL")) {
			String value02 = parm.getValue02();
			if (StringHelper.isEmpty(value02)) {
				return false;
			}

			String comId = prod.getIssuerId().toString();
			logger.info("comId = {}", comId);
			if (value02.contains("-"+comId+"-")) {
				logger.info("contain the comID");
				return true;
			} else {
				logger.info("not contain the comID");
				return false;
			}

		} else {
			logger.info("will not check");
			return false;
		}
	}
}
